Skip to content

Always offer the teacher-layer selector via ?exe-teacher=1#62

Merged
erseco merged 1 commit into
mainfrom
feature/teacher-mode-url-param
Jun 26, 2026
Merged

Always offer the teacher-layer selector via ?exe-teacher=1#62
erseco merged 1 commit into
mainfrom
feature/teacher-mode-url-param

Conversation

@erseco

@erseco erseco commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Do not merge until exelearning/exelearning#1972 is merged. This PR depends on the core ?exe-teacher=1 contract introduced there.

Summary

eXeLearning core (PR exelearning/exelearning#1972, fixes #1772) now hides teacher-only content by default in exports and previews. Revealing it requires loading the package with ?exe-teacher=1, which makes an in-package "teacher layer" selector available (OFF by default; the viewer activates it, the choice is persisted in localStorage, and the package's own JS propagates the param across in-package navigation).

Nextcloud has no teacher-mode handling today — it just renders the ELPX viewer in a sandboxed iframe. After #1972 merges, the viewer would serve the student view only and teacher-only content would become unreachable (a regression vs today, where the core showed the toggle to everyone).

Because the Nextcloud viewer is a personal file viewer — the person opening the package is effectively its author/teacher — we always make the selector available by appending ?exe-teacher=1 to the package index URL.

Implementation

The param is appended in one place: buildSandboxedIframe() in src/elpx/iframe-renderer.ts, via a small withTeacherMode() helper.

This is the single funnel where the resolved index URL becomes iframe.src. Both rendering paths pass through it with the index entry only:

  • the Service Worker path — createPackageIframe()buildSandboxedIframe(), and
  • the server-side asset fallback — attachServerIframe()buildSandboxedIframe().

Subresources are never built here; they are fetched by the package's own relative links (resolved by the SW or the AssetController). So only the top-level page carries the param, and the package's JS propagates it onward — exactly the core contract.

Why it's Service-Worker-safe: the SW keys requests on url.pathname only (src/sw/exelearning-sw.jsmatchRuntimeUrl(url.pathname)), and parseRuntimeUrl()/path resolution in paths.ts parse the pathname too. An extra query string on the index src is therefore harmless and does not affect request matching. The helper also guards against a double-append (includes('?') ? '&' : '?', and a no-op when the param is already present).

Testing

Commands run from the repo root (Node 22):

  • npx vitest run tests/js/iframe-renderer.test.ts5 passed (new spec)
  • npx vitest run59 passed (6 files; full suite)
  • npx eslint --ext .js,.ts,.vue --max-warnings 0 src → clean (exit 0)
  • npx biome lint src/elpx/iframe-renderer.ts tests/js/iframe-renderer.test.ts → no findings
  • npx vue-tsc --noEmit → clean (exit 0)

The new spec (tests/js/iframe-renderer.test.ts) asserts the built iframe src contains exe-teacher=1 for both the runtime and asset-fallback index URLs, uses & when a query already exists, and never double-appends.

Why this fits the future direction

Teacher-layer visibility is driven purely by the package's own URL parameter, with no host DOM/CSS/JS injection into the iframe content. The host only chooses the entry URL; everything else lives inside the sandboxed package. This advances the goal of isolating embedded resource content from the host.

@github-actions

Copy link
Copy Markdown
Contributor

Preview this PR in the Nextcloud Playground

Open this PR in the Nextcloud Playground

A fresh Nextcloud boots in your browser with this branch's exelearning app installed and enabled (log in as admin / admin). Two sample .elpx are seeded under exelearning-samples/ in Files — click one to open the viewer.

eXeLearning editor: v4.0.1 (overlaid at boot from the upstream release).

@erseco erseco merged commit 2982561 into main Jun 26, 2026
14 checks passed
@erseco erseco deleted the feature/teacher-mode-url-param branch June 26, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant